
/**
 *  \file gatt_db_internal.h
 *
 *  Module Internal Header File contains structure definitions including tables
 *  maintained by the module
 */

/*
 *  Copyright (C) 2013. Mindtree Ltd.
 *  All rights reserved.
 */

#ifndef _H_GATT_DB_INTERNAL_
#define _H_GATT_DB_INTERNAL_

/* --------------------------------------------- Header File Inclusion */
#include "BT_common.h"
#include "BT_device_queue.h"
#include "BT_security.h"
#include "BT_att_api.h"
#include "BT_gatt_db_api.h"
#include "gatt_defines.h"

/* --------------------------------------------- Global Definitions */

#ifdef GATT_DB_NO_DEBUG
#define GATT_DB_ERR          BT_debug_null
#else /* GATT_DB_NO_DEBUG */
#ifdef VAR_ARG_IN_MACRO_NOT_SUPPORTED
#define GATT_DB_ERR
#else
#define GATT_DB_ERR(...)     BT_debug_error(BT_MODULE_ID_GATT_DB, __VA_ARGS__)
#endif /* VAR_ARG_IN_MACRO_NOT_SUPPORTED */
#endif /* GATT_DB_NO_DEBUG */
/* #define NO_MUTE */

#ifdef GATT_DB_DEBUG
#ifdef VAR_ARG_IN_MACRO_NOT_SUPPORTED
#define GATT_DB_TRC
#define GATT_DB_INF
#define GATT_DB_debug_dump_bytes(data, datalen)
#else
#define GATT_DB_TRC(...)     BT_debug_trace(BT_MODULE_ID_GATT_DB,__VA_ARGS__)
#define GATT_DB_INF(...)     BT_debug_info(BT_MODULE_ID_GATT_DB,__VA_ARGS__)
#define GATT_DB_debug_dump_bytes(data, datalen) BT_debug_dump_bytes(BT_MODULE_ID_GATT_DB, (data), (datalen))
#endif /* VAR_ARG_IN_MACRO_NOT_SUPPORTED */
#else /* GATT_DB_DEBUG */
#define GATT_DB_TRC          BT_debug_null
#define GATT_DB_INF          BT_debug_null
#define GATT_DB_debug_dump_bytes(data, datalen)
#endif /* GATT_DB_DEBUG*/

/*
 *  Locks the GENERIC_MANAGER Mutex which prevents any global variable being
 *  overwritten by any function. It returns an error if mutex lock fails.
 */
#define GATT_DB_LOCK()\
        GATT_DB_TRC ("[GATT DB]: LOCK");\
        BT_MUTEX_LOCK(gatt_db_mutex, GATT_DB)

/*
 *  Locks the GATT_DB_mutex which prevents any global variable being
 *  overwritten by any function. To be used in void function as it
 *  returns no error.
 */
#define GATT_DB_LOCK_VOID()\
        GATT_DB_TRC ("[GATT DB]: LOCK Void");\
        BT_MUTEX_LOCK_VOID(gatt_db_mutex, GATT_DB)

/*
 *  Unlocks the GATT_DB_mutex which realeses the global variables
 *  to be written into. It returns an error if mutex unlock fails.
 */
#define GATT_DB_UNLOCK()\
    GATT_DB_TRC ("[GATT DB]: UNLOCK");\
    BT_MUTEX_UNLOCK(gatt_db_mutex, GATT_DB)

/*
 *  Unlocks the GATT_DB_mutex which realeses the global variables
 *  to be written into. To be used in void functions as it returns
 *  no error.
 */
#define GATT_DB_UNLOCK_VOID()\
        GATT_DB_TRC ("[GATT DB]: UNLOCK Void");\
        BT_MUTEX_UNLOCK_VOID(gatt_db_mutex, GATT_DB)

#define GATT_DB_alloc_mem(size)\
        BT_alloc_mem(size)

#define GATT_DB_free_mem(ptr)\
        BT_free_mem(ptr)

/* Null Check for GATT DB API Parameters */
#ifdef GATT_DB_NO_NULL_PARAM_CHECK
#define GATT_DB_NULL_CHECK(x)
#else /* GATT_DB_NO_NULL_PARAM_CHECK */
#define GATT_DB_NULL_CHECK(x)\
        if (NULL == (x))\
        {\
            GATT_DB_ERR(\
            "[GATT] NULL Parameter Unacceptable\n");\
            return GATT_DB_NULL_PARAMETER_NOT_ALLOWED;\
        }
#endif /* GATT_DB_NO_NULL_PARAM_CHECK */

#define GATT_DB_VALIDATE_ATTR_HANDLE(x)\
        if (ATT_INVALID_ATTR_HANDLE_VAL == (x) ||\
        (x) > GATT_DB_LAST_RECORD_HANDLE)\
        {\
            GATT_DB_ERR(\
            "[GATT] Invalid Handle 0x%04X",(x));\
            return GATT_DB_INVALID_ATTR_HANDLE;\
        }

#define GATT_DB_VALIDATE_INSTANCE(x)\
        if ((GET_GATT_SERVICE_COUNT() <= (x)->service_id) || \
           (GET_GATT_CHARACTERISTIC_COUNT() <= (x)->char_id) || \
           (BT_MAX_DEVICE_QUEUE_SIZE <= (x)->device_id ))\
        {\
            GATT_DB_ERR(\
            "[GATT]: Invalid GATT Handle 0x%02X:0x%02X:0x%02X",\
            (x)->device_id,(x)->service_id,(x)->char_id);\
            return GATT_DB_INVALID_INSTANCE;\
        }

#ifdef GATT_DB_SUPPORT_128_BIT_UUID
#define GATT_DB_GET_SERVICE_UUID_LEN(inst)\
        (GATT_DB_SER_CHECK_PRPTY((inst),GATT_DB_SER_128_BIT_UUID_FORMAT)?\
         ATT_128_BIT_UUID_SIZE:ATT_16_BIT_UUID_SIZE)
#else /* GATT_DB_SUPPORT_128_BIT_UUID */
#define GATT_DB_GET_SERVICE_UUID_LEN(inst)           (ATT_16_BIT_UUID_SIZE)
#endif /* GATT_DB_SUPPORT_128_BIT_UUID */

#define GATT_DB_CHAR_DECL_LENGTH                   5
#define GATT_DB_CLI_CNFG_LENGTH                    2
#define GATT_DB_SER_CNFG_LENGTH                    2

#define GATT_DB_CHAR_DECL_PRPTY_LENGTH             1
#define GATT_DB_CHAR_DECL_HNDL_LENGTH              2

/**
 * Used to to describe that the Highler Layer Descriptor UUID is
 * in 128 bit format
 */
#define GATT_DB_HLD_128_BIT_UUID_FORMAT         0x80

#ifdef GATT_DB_SUPPORT_128_BIT_UUID

#define GATT_DB_CHAR_GET_128_BIT_UUID(dest,cid)\
        BT_mem_copy\
        (\
            (dest),\
            gatt_db_128_uuid_val_arr[gatt_characteristic_g[(cid)].uuid].uuid128,\
            ATT_128_BIT_UUID_SIZE\
        )

#define GATT_DB_SER_GET_128_BIT_UUID(dest,sid)\
        BT_mem_copy\
        (\
            (dest),\
            gatt_db_128_uuid_val_arr[gatt_service_g[(sid)].uuid].uuid128,\
            ATT_128_BIT_UUID_SIZE\
        )

#endif /* GATT_DB_SUPPORT_128_BIT_UUID */

#define GATT_DB_EXT_PRPTY_MASK                         0x00FFFF00
#define GATT_DB_ADV_DESC_MASK                          0x3C000000

#define GATT_DB_PRST_DESC_MASK                         0x00000000
#define GATT_DB_USR_DESC_MASK                          0x04000000
#define GATT_DB_AGGRTE_DESC_MASK                       0x0C000000
#define GATT_DB_HLD_DESC_MASK                          0x1C000000

#define GATT_DB_EXTND_PRPTY_VAL_LEN                    2
#define GATT_DB_PRST_FRMT_VAL_LEN                      7

#define GATT_DB_SERVICE_UUID_FN_INDEX       0
#define GATT_DB_CHAR_UUID_FN_INDEX          1
#define GATT_DB_INVALID_UUID_FN_INDEX       2

#define GATT_DB_SERVICE_VALUE_FN_INDEX       0
#define GATT_DB_CHAR_VALUE_FN_INDEX          1
#define GATT_DB_INVALID_VALUE_FN_INDEX       2

#define GATT_DB_CHAR_HANDLER_INVALID_INDEX   0xFF

#define GATT_DB_FETCH_UUID_FN_LIST_SIZE      3
#define GATT_DB_FETCH_VALUE_FN_LIST_SIZE     3

#define GATT_DB_CHAR_CLI_CNFG_OP_FLAG       0x10
#define GATT_DB_CHAR_SER_CNFG_OP_FLAG       0x20

#define GATT_DB_COMPARE_VALUES(value_1,value_2,length)\
        (((NULL == (value_1))|| (NULL == ((value_1)->val))|| \
        (NULL == (value_2)) || (0 == (length)))? API_SUCCESS:\
        ((0 == BT_mem_cmp((value_1)->val,(value_2),(length)))?\
        API_SUCCESS : GATT_DB_TYPE_MISMATCH))

#define GATT_DB_PACK_16_BIT_UUID(dest,uuid)\
        *(dest) = (uuid)

#define GATT_DB_CHAR_START_HANDLE(index)\
        gatt_characteristic_g[(index)].start_handle

#define GATT_DB_GET_CHAR_ATTR_COUNT(index)\
        gatt_characteristic_g[(index)].list.count

#define GATT_DB_CHAR_END_HANDLE(index)\
        (GATT_DB_CHAR_START_HANDLE((index)) + \
        (GATT_DB_GET_CHAR_ATTR_COUNT((index)) - 1))

#define GATT_DB_GET_CHARACTERISTIC_UUID_VALUE(index)\
        (&gatt_characteristic_g[(index)].uuid)

#define GATT_DB_GET_CHAR_DESC(index)\
        (&gatt_characteristic_g[(index)].list)

#define GATT_DB_CHAR_CHECK_PRPTY(cid,prpty)\
        ((prpty) == (GATT_DB_GET_CHAR_DESC((cid)) & (prpty)))

#define GATT_DB_GET_SER_DESC(index)\
        (gatt_service_g[(index)].desc)

#define GATT_DB_SER_CHECK_PRPTY(sid,prpty)\
        ((prpty) == (GATT_DB_GET_SER_DESC((sid)) & (prpty)))

#define GATT_DB_COMPARE_16_BIT_UUID(u1,u2)\
       (((u1) == (u2))? BT_TRUE: BT_FALSE)

#define GATT_DB_GET_CHAR_DESC_OFFSET(c_id,mask,index)\
        (index) = (gatt_characteristic_g[(c_id)].desc_sdata_index + 0);

#define GATT_DB_CHECK_IF_CHAR_DEF_HNDL(cid,hndl)\
         ((GATT_DB_CHAR_START_HANDLE((cid)) == (hndl)) ? BT_TRUE : BT_FALSE)

#define GATT_DB_VALIDATE_UUID_FRMT_LENGTH(frmt,length)\
        ((((ATT_128_BIT_UUID_SIZE == (length)) && \
        (ATT_128_BIT_UUID_FORMAT == (frmt))) || \
        ((ATT_16_BIT_UUID_SIZE == (length)) && \
        (ATT_16_BIT_UUID_FORMAT == (frmt)))) ? BT_TRUE : BT_FALSE)

#define GATT_INVALID_DESC_INDEX 0xFFFF

#define GATT_DB_GET_UUID_LENGTH(i)\
        ((GATT_DB_128_BIT_UUID_FORMAT ==\
        (GATT_DB_GET_ATTR_AUX_PRPTY((i)) & GATT_DB_128_BIT_UUID_FORMAT)) ?\
        ATT_128_BIT_UUID_SIZE : ATT_16_BIT_UUID_SIZE)

#define GATT_DB_GET_ATTR_PRPTY(i)\
        gatt_db_attr_table_g[(i)].desc_property

#define GATT_DB_GET_ATTR_AUX_PRPTY(i)\
        gatt_db_attr_table_g[(i)].aux_property

#define GATT_DB_GET_ATTR_VALUE(i)\
        gatt_db_attr_table_g[(i)].data_offset

#define GATT_DB_GET_ATTR_LENGTH(i)\
        gatt_db_attr_table_g[(i)].length

#define GATT_DB_GET_NEXT_ATTR(i)\
        gatt_db_attr_table_g[(i)].next

#define GATT_ACCESS_TYPE_VAL(i)\
        &gatt_const_uuid_arr_g[gatt_type_table_g[(i)].uuid_offset]

#define GATT_DB_LAST_RECORD_HANDLE\
        gatt_service_g[GET_GATT_SERVICE_COUNT()-1].end_handle

#define GATT_DB_GET_PEER_SPECIFIC_VALUE(i)\
        (gatt_db_peer_specific_val_arr_g +\
        (GET_GATT_DB_PEER_VALUE_ARRAY_SIZE() *\
        (BT_MAX_DEVICE_QUEUE_SIZE - ((i) + 1))))

#define GATT_DB_GET_CONST_PEER_SPECIFIC_VALUE()\
        gatt_db_const_peer_specific_val_arr_g

/** Macro to fetch the handle range of a given service */
#define GATT_DB_GET_SER_RANGE(sid,sh,eh)\
        (sh) = (gatt_service_g[(sid)].start_handle);\
        (eh) = (gatt_service_g[(sid)].end_handle)

/** Macro to fetch the Char ID range of a given service */
#define GATT_DB_GET_CHAR_ID_RANGE(sid,csi,cei)\
        (csi) = (gatt_service_g[(sid)].char_start_index);\
        (cei) = (gatt_service_g[(sid)].char_end_index)

/** Macro to fetch the Char Count of a given service */
#define GATT_DB_GET_SER_CHAR_COUNT(sid,cnt)\
        (cnt) = (((gatt_service_g[(sid)].char_end_index) - (gatt_service_g[(sid)].char_start_index)) + 1)

#ifndef GATT_DB_HAVE_REGISTERATION_SUPPORT
extern DECL_CONST GATT_DB_SERVICE gatt_service[];
extern DECL_CONST GATT_DB_CHARACERISTIC gatt_characteristic[];
extern DECL_CONST UCHAR gatt_const_value_arr[];
extern DECL_CONST UCHAR gatt_const_uuid_arr[];
extern DECL_CONST GATT_DB_DESC_DATA gatt_db_attr_table[];
extern DECL_CONST GATT_ATTR_TYPE gatt_type_table[];
extern UCHAR gatt_db_peer_specific_val_arr[];
extern DECL_CONST UCHAR gatt_db_const_peer_specific_val_arr[];
extern UCHAR gatt_value_arr[];

#ifndef GATT_DB_HAVE_STATIC_CONFIGURATION
extern DECL_CONST UCHAR  gatt_service_count;
extern DECL_CONST UCHAR  gatt_characteristic_count;
extern DECL_CONST UCHAR  gatt_db_max_type_count;
extern DECL_CONST UCHAR  gatt_db_peer_val_arr_size;

#ifdef STORAGE_RETENTION_SUPPORT
extern DECL_CONST UINT16 gatt_value_array_size;
extern DECL_CONST UINT16 gatt_db_max_peer_config;
#endif /* STORAGE_RETENTION_SUPPORT */
#endif /* GATT_DB_HAVE_STATIC_CONFIGURATION */
#endif /* GATT_DB_HAVE_REGISTERATION_SUPPORT */

#ifdef GATT_DB_HASH_SUPPORT
/** GATT Database Cache Types */
/**
 *  GATT Database - Cache Type-1 (HTV):
 *  Handle, Type, and Value to be packed/concatenated for
 *  following attributes
 *  1. <<Primary Service>>
 *  2. <<Secondary Service>>
 *  3. <<Included Service>>
 *  4. <<Characteristic>>
 *  5. <<Characteristic Extended Properties>>
 */
#define GATT_DB_CACHE_TYPE_HTV        0x01

/**
 *  GATT Database - Cache Type-2 (HT):
 *  Handle and Type to be packed/concatenated for following attributes
 *  1. <<Characteristic User Description>>
 *  2. <<Client Characteristic Configuration>>
 *  3. <<Server Characteristic Configuration>>
 *  4. <<Characteristic Format>>
 *  5. <<Characteristic Aggregate Format>>
 */
#define GATT_DB_CACHE_TYPE_HT         0x02

/** GATT Database - Invalid Cache Type */
#define GATT_DB_CACHE_TYPE_INVALID    0xFF

#endif /* GATT_DB_HASH_SUPPORT */

/* --------------------------------------------- Data Types/ Structures */

typedef API_RESULT (* GATT_DB_FETCH_UUID)
                   (
                        /* IN */ ATT_ATTR_HANDLE    handle,
                        /* IN */ UCHAR              index,
                        /* IN */ UCHAR              frmt,
                        /* IN */ ATT_VALUE          * uuid
                   ) DECL_REENTRANT;

typedef API_RESULT ( *GATT_DB_FETCH_VALUE)
                   (
                        /* IN */ GATT_DB_HANDLE            * db_handle,
                        /* IN */ ATT_HANDLE_VALUE_PAIR     * handle,
                        /* IN */ UINT16                    offset,
                        /* IN */ UCHAR                     write_flag
                   ) DECL_REENTRANT;

#ifdef BT_STORAGE
/** Abstracts storage module handlers */
typedef void (*GATT_DB_STORAGE_HNDLR)(void);
#endif /* BT_STORAGE */

typedef UINT16 GATT_DB_ATTR_INDEX;

/* --------------------------------------------- Functions */

#ifdef BT_STORAGE
void gatt_db_storage_write(void);
void gatt_db_storage_read(void);
void gatt_db_rstorage_cb (UCHAR id, UCHAR type, UCHAR action);
#endif /* BT_STORAGE */

API_RESULT gatt_db_check_char_handle_in_range
           (
               /* IN */  ATT_ATTR_HANDLE   handle,
               /* IN */  UCHAR             c_id,
               /* OUT */ UCHAR             * attr_prpty,
               /* OUT */ UINT16            * next
           );

API_RESULT gatt_db_get_service_handle
           (
               /* IN */  ATT_ATTR_HANDLE    handle,
               /* OUT */ UCHAR              * service_id
           );

API_RESULT gatt_db_get_char_handle
           (
               /* IN */  ATT_ATTR_HANDLE    handle,
               /* IN */  UCHAR              service_id,
               /* OUT */ UINT16             * next,
               /* OUT */ UCHAR              * char_id,
               /* OUT */ UCHAR              * flags
           );

API_RESULT gatt_db_get_char_uuid
           (
               /* IN */ ATT_ATTR_HANDLE    handle,
               /* IN */ UCHAR              char_index,
               /* IN */ UCHAR              frmt,
               /* IN */ ATT_VALUE          * uuid
           );

API_RESULT gatt_db_get_char_value
           (
                /* IN */    GATT_DB_HANDLE           * db_handle,
                /* INOUT */ ATT_HANDLE_VALUE_PAIR    * handle_value,
                /* IN */    UINT16                   offset,
                /* IN */    UCHAR                    flag
           );

API_RESULT gatt_db_get_service_uuid
           (
               /* IN */ ATT_ATTR_HANDLE    handle,
               /* IN */ UCHAR              service_index,
               /* IN */ UCHAR              frmt,
               /* IN */ ATT_VALUE          * uuid
           );

API_RESULT gatt_db_get_service_value
           (
               /* IN */ GATT_DB_HANDLE           * db_handle,
               /* IN */ ATT_HANDLE_VALUE_PAIR    * handle_value,
               /* IN */ UINT16                   offset,
               /* IN */ UCHAR                    flag
           );

API_RESULT gatt_db_compare_char_value
           (
               /* IN */ ATT_VALUE          * value,
               /* IN */ ATT_ATTR_HANDLE    handle,
               /* IN */ UCHAR              char_id,
               /* IN */ UCHAR              frmt
           );

API_RESULT gatt_db_check_security_access_pl
           (
               /* IN */ GATT_DB_HANDLE  * handle
           );

API_RESULT gatt_db_get_cnfg_index
           (
               /* IN */  GATT_DB_HANDLE    * db_handle,
               /* OUT */ UCHAR             * char_id
           );

API_RESULT gatt_db_init_peer_specific_info
           (
               /* IN */ DEVICE_HANDLE    * device_handle
           );

API_RESULT gatt_db_access_desc_value
           (
               /* IN */    GATT_DB_HANDLE           * db_handle,
               /* IN */    UCHAR                    mask,
               /* INOUT */ ATT_HANDLE_VALUE_PAIR    * handle_value,
               /* IN */    UINT16                   offset,
               /* IN */    UCHAR                    flag
           );

API_RESULT gatt_db_access_hld_uuid
           (
               /* IN */ UCHAR       char_id,
               /* IN */ UCHAR       uuid_format,
               /* IN */ ATT_UUID    * uuid
           );

UINT16 gatt_get_char_desc_index
       (
           /* IN */ ATT_ATTR_HANDLE   handle,
           /* IN */ UCHAR             cid
       );

API_RESULT gatt_get_type_val
           (
               /* IN */  ATT_HANDLE_RANGE    * range,
               /* IN */  ATT_VALUE           * type,
               /* IN */  ATT_VALUE           * value,
               /* OUT */ GATT_DB_ATTR_INDEX  * attr
           );

API_RESULT gatt_get_type_id
           (
               /* IN */  ATT_VALUE          * type,
               /* OUT */ GATT_TYPE_INDEX    * type_id
           );

API_RESULT gatt_get_attr_gatt_handle
           (
               /* IN */  GATT_DB_ATTR_INDEX    attr,
               /* OUT */ GATT_DB_HANDLE        * handle
           );

API_RESULT gatt_search_attr_by_handle
           (
               /* IN */  ATT_ATTR_HANDLE      handle,
               /* OUT */ GATT_DB_ATTR_INDEX   * attr
           );

void gatt_db_update_peer_cnfg_table (void);

#define gatt_check_security(h) gatt_db_check_security_access_pl(h)

API_RESULT gatt_db_validate_transport_access
           (
               /* IN */ GATT_DB_HANDLE    * db_handle
           );

#endif /* _H_GATT_DB_INTERNAL_ */
